﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using AutoMapper;
using Microsoft.Practices.Prism;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.ViewModel;
using Sautom.ClientComunication;
using Sautom.ClientComunication.CommandService;
using Sautom.ClientComunication.FileService;
using Sautom.ClientComunication.Helpers;
using Sautom.ClientComunication.QueriesService;
using Sautom.ClientComunication.Services;
using Sautom.Modules.Client.Commands;
using Sautom.Modules.Client.Controls.ViewModels;
using Sautom.Modules.Client.Models;

namespace Sautom.Modules.Client.ViewModels
{
    public sealed class ClientDetailsViewModel : NavigationAwareNotificationObject
    {
        #region Constructor
        public ClientDetailsViewModel(IRegionManager regionManager, ServiceFactory serviceFactory, ClientFileListViewModel clientFileListViewModel)
        {
            RegionManager = regionManager;
            ClinetFileListViewModel = clientFileListViewModel;

            QueriesServiceClient = serviceFactory.GetQueriesService();
            CommandServiceClient = serviceFactory.GetCommandsService();
            FileServiceClient = serviceFactory.GetFilesService();

            ClientFileHelper = new ClientFileHelper(null);

            //todo commands to separate classes
            BackCommand = new SimpleNavigateCommand(regionManager, RegionProvider.MainRegion, PathProvider.ClientIndex);
            
            EditCommand = new DelegateCommand(ExecuteClientEditCommand);
            AddOrderCommand = new DelegateCommand(ExecuteAddOrderCommand);
            AirlineTicketCommand = new DelegateCommand(ExecuteAirlineTicketCommand);
            ContractCommand = new DelegateCommand(ExecuteContractCommand);

            EditOrderAdvancedCommand = new DelegateCommand(ExecuteEditOrderAdvancedCommand);
            
            SelectedOrderViewModel = new OrderViewerViewModel(new PrintOrderDetailsCommand(ClientFileHelper, FileServiceClient));
        }

        #endregion

        public ClientFileListViewModel ClinetFileListViewModel { get; set; }

        #region Commands
        public ICommand BackCommand { get; private set; }
        public ICommand EditCommand { get; private set; }
        public ICommand AddOrderCommand { get; private set; }
        public ICommand AirlineTicketCommand { get; private set; }
        public ICommand ContractCommand { get; private set; }
        public ICommand EditOrderAdvancedCommand { get; private set; }
        
        private void ExecuteEditOrderAdvancedCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.Id.ToString() }, { "orderId", this.SelectedOrder.Id.ToString() } };
            var uri = new Uri(PathProvider.EditOrderAdvanced + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);
        }

        private void ExecuteAirlineTicketCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.Id.ToString() }, { "orderId", this.SelectedOrder.Id.ToString() } };
            var uri = new Uri(PathProvider.AirlineTicketView + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);

        }

        private void ExecuteContractCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.Id.ToString() }, { "orderId", this.SelectedOrder.Id.ToString() } };
            var uri = new Uri(PathProvider.ContractView + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);
        }

        private void ExecuteAddOrderCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.Id.ToString() } };
            var uri = new Uri(PathProvider.ClientAddNewOrder + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);
        }

        private void ExecuteClientEditCommand()
        {
            var uriQuery = new UriQuery { { "clientId", this.Id.ToString() } };
            var uri = new Uri(PathProvider.ClientEdit + uriQuery, UriKind.Relative);
            RegionManager.RequestNavigate(RegionProvider.MainRegion, uri);
        }
        #endregion

        #region Properties
        private IRegionManager RegionManager { get; set; }
        private IQueriesService QueriesServiceClient { get; set; }
        private ICommandService CommandServiceClient { get; set; }

        private ClientFileHelper ClientFileHelper { get; set; }
        private IFileService FileServiceClient { get; set; }
        #endregion

        #region INavigationAware implementation
        public override void OnNavigatedTo(NavigationContext navigationContext)
        {
            base.OnNavigatedTo(navigationContext);
            
            // Initial load - Load based on ID passed in
            string id = navigationContext.Parameters["clientId"];
            if (string.IsNullOrWhiteSpace(id)) return;

            ClientViewDtoOutput client = QueriesServiceClient.GetClientForView(Guid.Parse(id));
            Mapper.CreateMap<ClientViewDtoOutput, ClientDetailsViewModel>()
                .ForMember(foo => foo.NameRu,
                           foo => foo.ResolveUsing(bar => bar.LastName + " " + bar.FirstName + " " + bar.MiddleName));
            Mapper.Map(client, this);

            ClinetFileListViewModel.Configure(client.Id);

            SelectedOrder = Orders.FirstOrDefault(rec => rec.IsActive) ?? Orders.FirstOrDefault();

            Comments = client.Comments.ToList();
        }

        public override void OnNavigatedFrom(NavigationContext navigationContext)
        {
            base.OnNavigatedFrom(navigationContext);

            SelectedOrder = SelectedOrder;

            Mapper.CreateMap<OrderItemDtoOutput, OrderEditDtoInput>()
                .ForMember(d => d.EmbassyDocs, o => o.ResolveUsing(v => v.Docs));

            var updatedOrders = Orders.Where(rec => rec.IsActive).Select(Mapper.Map<OrderEditDtoInput>).ToArray();
            CommandServiceClient.BulkUpdateOrders(updatedOrders);

            if (!string.IsNullOrWhiteSpace(Comment))
            {
                CommandServiceClient.AddClientComment(Id, Comment);
            }
        }

        #endregion

        #region Client properties

        private string _comment;
        public string Comment
        {
            get { return _comment; }
            set
            {
                _comment = value;
                RaisePropertyChanged(() => Comment);
            }
        }

        private List<ManagerCommentItemDtoOutput> _comments;
        public List<ManagerCommentItemDtoOutput> Comments
        {
            get { return _comments; }
            set
            {
                _comments = value;
                RaisePropertyChanged(() => Comments);
            }
        }

        #region Client
        public Guid Id { get; set; }

        private string _personalNumber;
        public string PersonalNumber
        {
            get { return _personalNumber; }
            set
            {
                _personalNumber = value;
                RaisePropertyChanged(() => PersonalNumber);
            }
        }

        private string _nameLat;
        public string NameLat
        {
            get { return _nameLat; }
            set
            {
                _nameLat = value;
                RaisePropertyChanged(() => NameLat);
            }
        }

        private string _nameRu;
        public string NameRu
        {
            get { return _nameRu; }
            set
            {
                _nameRu = value;
                RaisePropertyChanged(() => NameRu);
            }
        }

        private DateTime? _birthDate;
        public DateTime? BirthDate
        {
            get { return _birthDate; }
            set
            {
                _birthDate = value;
                RaisePropertyChanged(() => BirthDate);
            }
        }

        private string _passportInfo;
        public string PassportInfo
        {
            get { return _passportInfo; }
            set
            {
                _passportInfo = value;
                RaisePropertyChanged(() => PassportInfo);
            }
        }

        private string _passportByWhom;
        public string PassportByWhom
        {
            get { return _passportByWhom; }
            set
            {
                _passportByWhom = value;
                RaisePropertyChanged(() => PassportByWhom);
            }
        }

        private DateTime? _passportFromDate;
        public DateTime? PassportFromDate
        {
            get { return _passportFromDate; }
            set
            {
                _passportFromDate = value;
                RaisePropertyChanged(() => PassportFromDate);
            }
        }

        private DateTime? _passportByDate;
        public DateTime? PassportByDate
        {
            get { return _passportByDate; }
            set
            {
                _passportByDate = value;
                RaisePropertyChanged(() => PassportByDate);
            }
        }

        private string _address;
        public string Address
        {
            get { return _address; }
            set
            {
                _address = value;
                RaisePropertyChanged(() => Address);
            }
        }

        private string _phoneFirst;
        public string PhoneFirst
        {
            get { return _phoneFirst; }
            set
            {
                _phoneFirst = value;
                RaisePropertyChanged(() => PhoneFirst);
            }
        }

        private string _phoneSecond;
        public string PhoneSecond
        {
            get { return _phoneSecond; }
            set
            {
                _phoneSecond = value;
                RaisePropertyChanged(() => PhoneSecond);
            }
        }

        //parent section
        private string _parentName;
        public string ParentName
        {
            get { return _parentName; }
            set
            {
                _parentName = value;
                RaisePropertyChanged(() => ParentName);
            }
        }

        private string _parentAddress;
        public string ParentAddress
        {
            get { return _parentAddress; }
            set
            {
                _parentAddress = value;
                RaisePropertyChanged(() => ParentAddress);
            }
        }

        private string _parentPhone;
        public string ParentPhone
        {
            get { return _parentPhone; }
            set
            {
                _parentPhone = value;
                RaisePropertyChanged(() => ParentPhone);
            }
        }

        private string _parentPassportInfo;
        public string ParentPassportInfo
        {
            get { return _parentPassportInfo; }
            set
            {
                _parentPassportInfo = value;
                RaisePropertyChanged(() => ParentPassportInfo);
            }
        }

        public bool IsParentSection
        {
            get { return BirthDate.HasValue && Math.Abs(BirthDate.Value.Date.Year - DateTime.Now.Date.Year) < 18; } //todo BL detected
        }

        #endregion

        private ObservableCollection<OrderItemDtoOutput> _orders;
        public ObservableCollection<OrderItemDtoOutput> Orders
        {
            get { return _orders; }
            set
            {
                _orders = value;
                RaisePropertyChanged(() => Orders);
            }
        }

        private OrderItemDtoOutput _selectedOrder;
        public OrderItemDtoOutput SelectedOrder
        {
            get { return _selectedOrder; }
            set
            {
                _selectedOrder = value;
                RaisePropertyChanged(() => SelectedOrder);

                SelectedOrderViewModel.Order = value;
            }
        }

        private OrderViewerViewModel _selectedOrderViewModel;
        public OrderViewerViewModel SelectedOrderViewModel
        {
            get { return _selectedOrderViewModel; }
            private set
            {
                _selectedOrderViewModel = value;
                RaisePropertyChanged(() => SelectedOrderViewModel);
            }
        }

        #endregion
    }
}
